using System;
using System.Collections;
using System.Threading.Tasks;


namespace MyUtility.Operation
{

    public abstract class AsyncOperationBase : IEnumerator
    {
        /// <summary>
        /// 状态
        /// </summary>
        public OperationStatus Status { get; protected set; } = OperationStatus.None;

        /// <summary>
        /// 错误信息
        /// </summary>
        public string Error { get; protected set; }

        /// <summary>
        /// 处理进度
        /// </summary>
        public float Progress { get; protected set; }

        /// <summary>
        /// 是否已经完成
        /// </summary>
        public bool IsDone
        {
            get
            {
                return Status == OperationStatus.Failed || Status == OperationStatus.Succeed;
            }
        }

        /// <summary>
        /// 完成事件
        /// </summary>
        public event Action<AsyncOperationBase> Completed
        {
            add
            {
                if (IsDone)
                    value.Invoke(this);
                else
                    _callback += value;
            }
            remove
            {
                _callback -= value;
            }
        }

        /// <summary>
        /// 异步操作任务
        /// </summary>
        public Task Task
        {
            get
            {
                if (_taskCompletionSource == null)
                {
                    _taskCompletionSource = new TaskCompletionSource<object>();
                    if (IsDone)
                        _taskCompletionSource.SetResult(null);
                }
                return _taskCompletionSource.Task;
            }
        }

        public abstract void Start();
        public abstract void Update();

        public void SetFinish()
        {
            Progress = 1f;
            _callback?.Invoke(this); //注意：如果完成回调内发生异常，会导致Task无限期等待
            if (_taskCompletionSource != null)
                _taskCompletionSource.TrySetResult(null);
        }

        public void SetStart()
        {
            Status = OperationStatus.Processing;
        }

        /// <summary>
        /// 清空完成回调
        /// </summary>
        protected void ClearCompletedCallback()
        {
            _callback = null;
        }

        #region 异步编程相关
        bool IEnumerator.MoveNext()
        {
            return !IsDone;
        }

        void IEnumerator.Reset()
        {
        }

        object IEnumerator.Current => null;
        private TaskCompletionSource<object> _taskCompletionSource;
        #endregion

        /// <summary>
        /// 用户请求的回调
        /// </summary>
        private Action<AsyncOperationBase> _callback;
    }
}